home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 6 / clantutr.zip / LESSON8 < prev    next >
Text File  |  1986-02-07  |  25KB  |  478 lines

  1. .NT
  2.  A NOTE ABOUT THE LESSONS in C 
  3. .b4-24R5C4
  4. These were written while the author was ~Ilearning~N  the language and since
  5. .R6C4
  6. they  are  ~Ifree~N ( to  copy  and/or  distribute ) there  is  a money-back
  7. .R7C4
  8. guarantee on the accuracy of each and every statement in the lessons (!)
  9. .R9C4
  10. The  ~Idisplay~N  program was written ( in C ) in order to provide a vehicle
  11. .R10C4
  12. for displaying the lessons.
  13. .R12C5
  14. .B
  15. P.J.Ponzo
  16. .B
  17. Dept. of Applied Math
  18. .B
  19. Univ. of Waterloo
  20. .B
  21. Ontario N2L 3G1
  22. .K16,32
  23. PonzoTUTOR
  24. .WNT
  25.     FILES FILES FILES   
  26. .R4C1
  27.     Whereas ~b~Igetchar()~N and ~b~Iprintf()~N will get characters from the 
  28.     keyboard and print to the screen (the 'standard' input/output), we can
  29.     ask other functions available in the C-library (and ones we write 
  30.     ourselves) to communicate with a ~Ifile on disk~N. Consider the excerpt:
  31.  
  32. 1  ~b~Imain(number,name)                                    ~N
  33. 2  ~b~Iint number;                                          ~N
  34. 3  ~b~Ichar *name[];                                        ~N
  35. 4  ~b~I{                                                    ~N
  36. 5  ~b~I    FILE *fp, *fopen();                              ~N
  37. 6  ~b~I    fp=fopen(name[1],"r");                           ~N
  38. 7  ~b~I    if (fp == NULL) {                                ~N
  39. 8  ~b~I        printf("\nSorry, can't open %s",name[1]);    ~N
  40. 9  ~b~I        exit(0);                                     ~N
  41. 10 ~b~I    }                                                ~N
  42. 11 ~b~I    /*  rest of program goes here */                 ~N
  43. .w
  44.     The above program is expected to read a file on disk. We compile/link
  45.     the program, giving it the name ~Iread~N. Then we type: ~Iread letter~N.
  46.     The arguments to ~b~Imain()~N are the ~b~Inumber~N ~I2~N and the ARRAY
  47.     of POINTERS ( ~b~Iname[]~N ) pointing to the strings: ~Iread~N and ~Iletter~N.
  48. .WR10C1
  49. ~V2  int number;                                          ~N
  50. ~V3  char *name[];                                        ~N
  51. .R20C1
  52.                                                                               
  53.                                                                               
  54.                                                                               
  55.                                                                               
  56. .R20C1
  57.     We declare the two arguments of ~b~Imain()~N to be ~b~Iint~N and ~b~Ichar *~N.
  58.     In our example, ~b~Inumber~N will have the value ~I2~N and ~b~Iname[0]~N will
  59.     be a pointer to the string ~Iread~N and ~b~Iname[1]~N will point to ~Iletter~N.
  60.     Now we are ready to begin ~b~I{~N our ~b~Imain()~N program ....
  61. .WR10C1
  62. 2  ~b~Iint number;                                          ~N
  63. 3  ~b~Ichar *name[];                                        ~N
  64. 4  ~b~I{                                                    ~N
  65. ~V5      FILE *fp, *fopen();                              ~N
  66. .R20C1
  67.                                                                               
  68.                                                                               
  69.                                                                               
  70.                                                                               
  71. .R20C1
  72.     To ~Iopen~N a disk file, we use ~b~IFILE~N which calls upon the C-library
  73.     to look after the mechanics of communicating with the operating system in
  74.     order to access the disk. After ~b~IFILE~N come two ~r~Ipointers~N (we
  75.     know they're pointers because of the ~b~I*~N ..right?).
  76. .WR20C1
  77.                                                                               
  78.                                                                               
  79.                                                                               
  80.                                                                               
  81. .R20C1
  82.   Of course, if we intend to use the C-library, we had better ~V#include~N it!
  83. .WK10,60
  84.  stdio.h!
  85. .R8C1
  86. ~V0  #include <stdio.h>                                   ~N
  87. .WR20C1
  88.     ~b~Ifp~N is a ~r~Ipointer~N variable which points to a FILE.                       
  89.     ~b~Ifopen()~N is a function which ~Ireturns~N a ~r~Ipointer~N to a FILE.
  90. .WR13C1
  91. 5  ~b~I    FILE *fp, *fopen();                              ~N
  92. ~V6      fp=fopen(name[1],"r");                           ~N
  93. .R20C1
  94.                                                                               
  95.                                                                               
  96. .R20C1
  97.     This calls upon the ~b~Ifopen()~N function to ~Iopen~N a file. The pointer
  98.     to the file ( which is ~Ireturn~Ned by ~b~Ifopen()~N ) is assigned to ~b~Ifp~N.
  99.     The ~b~I"r"~N means that access to the file is for ~I"r"~Neading ( as
  100.     opposed to "w"riting or "a"ppending ).
  101. .WR20C1
  102.                                                                               
  103.                                                                               
  104.                                                                               
  105.                                                                               
  106. .R20C1
  107.     How do we tell ~b~Ifopen()~N the name of the file which we want to open...?
  108.     ~b~Iname[]~N is an ARRAY of pointers, each pointing to a string.
  109. .WR20C1
  110.                                                                               
  111.                                                                               
  112. .R20C1
  113.     When we typed ~Iread letter~N, we passed to our ~b~Imain()~N program the
  114.     two strings ~Iread~N and ~Iletter~N. Now the pointer ~b~Iname[0]~N points to
  115.     ~Iread~N and ~b~Iname[1]~N will point to the string ~Iletter~N ...
  116. .WR20C1
  117.                                                                               
  118.                                                                               
  119.                                                                               
  120. .R20C1
  121.     ...so we give the name of the file to ~b~Ifopen()~N, namely ~b~Iname[1]~N.
  122. .K10,60
  123. of course
  124. .WR14C1
  125. 6  ~b~I    fp=fopen(name[1],"r");                           ~N
  126. ~V7      if (fp == NULL) {                                ~N
  127. ~V8          printf("\nSorry, can't open %s",name[1]);    ~N
  128. ~V9          exit(0);                                     ~N
  129. .R20C1
  130.                                                                               
  131.                                                                               
  132.                                                                               
  133.                                                                               
  134. .R20C1
  135.     The function ~b~Ifopen()~N is clever. If it can't open the file for some
  136.     reason (beer-on-the-disk) it ~Ireturn~Ns a NULL pointer.
  137.     We check, in Line 7, IF ~b~Ifp~N is EQUAL ( ~b~I==~N ) to ~b~INULL~N.
  138.     If so, we apologize ( Line 8 ) and ~b~Iexit~N the program ( Line 9 ).
  139. .WR15C1
  140. 7  ~b~I    if (fp == NULL) {                                ~N
  141. 8  ~b~I        printf("\nSorry, can't open %s",~Vname[1]~N~b~I);    ~N
  142. 9  ~b~I        ~Vexit(0)~N~b~I;                                     ~N
  143. .R20C1
  144.                                                                               
  145.                                                                               
  146.                                                                               
  147.                                                                               
  148. .R20C1
  149.     In Line 8 we ~b~Iprintf~N ~b~Iname[1]~N as a ~b~I%s~Ntring (of course).
  150.     The ~b~Iexit(0)~N (in Line 9 ) is new. It will exit our ~b~Imain()~N 
  151.     and return you to the operating system (e.g. DOS ). ( It also ~Icloses~N
  152.     any open files ).
  153. .WR20C1
  154.                                                                                
  155.                                                                               
  156.                                                                               
  157.                                                                               
  158. .R20C1
  159.     NOTE: We gave to ~b~Ifopen()~N the string which ~b~Iname[1]~N points to,
  160.           and we also give it to ~b~Iprintf()~N (namely ~Iletter~N, in this
  161.           example).
  162. .WNK10,32
  163.   phew!!  
  164. .WN
  165. 1  ~b~Imain(number,name)                                    ~N
  166. 2  ~b~Iint number;                                          ~N
  167. 3  ~b~Ichar *name[]                                         ~N
  168. 4  ~b~I{                                                    ~N
  169. 5  ~b~I    FILE *fp, *fopen();                              ~N
  170. 6  ~b~I    fp=fopen(*name[1],"r");                          ~N
  171. 7  ~b~I    if (fp == NULL) {                                ~N
  172. 8  ~b~I        printf("\nSorry, can't open %f",name[1]);    ~N
  173. 9  ~b~I        exit(0);                                     ~N
  174. 10 ~b~I    }                                                ~N
  175. 11 ~b~I    /*  now we read from the file */                 ~N
  176. ~V12     char c;                                          ~N
  177. ~V13     while ( (c=getc(fp)) != EOF  )                   ~N
  178. ~V14         printf("%c",c);                              ~N
  179. ~V15 }                                                    ~N
  180. .w
  181.  
  182.     Now we declare a ~b~Ichar c~N ( Line 12 ) and continually ~b~Igetc()~N
  183.     ~Ifrom the file which we opened~N ( in Line 6 ). Reference to this open
  184.     file is via its ~Ifile pointer~N ~b~Ifp~N ... hence we used ~b~Igetc(~Ffp~N~b~I)~N
  185.     to tell the ~b~Igetc()~N function which file to ~b~Iget~N the next
  186.     ~b~Ic~Nhar from. ( ~b~Igetc()~N is in ~b~Istdio.h~N ).
  187. .WR17C1
  188.                                                                               
  189.                                                                               
  190.                                                                               
  191.                                                                               
  192.                                                                               
  193. .R17C1
  194.     We (in this example) ~b~Iprintf()~N the ~%c~Nhar to the screen, ~b~Iwhile~N
  195.     ~b~Ic~N is NOT EQUAL ( ~b~I!=~N ) to the ~b~IEOF~N  character (which ~Ishould~N
  196.     indicate ~IE~Nnd ~IO~Nf ~IF~Nile ..if all goes well ..).
  197. .WR17C1
  198.                                                                               
  199.                                                                               
  200.                                                                               
  201.                                                                               
  202.                                                                               
  203. .R17C1
  204. .Q
  205. How many errors in the above program ? 
  206. 4
  207. .R21C1
  208.     Line 3 needs a ~Isemi-colon~N!
  209. .R3C1
  210. 3  ~b~Ichar *name[] ~Ftch! tch!~N~b~I~N
  211. .WR21C1
  212.     Line 6 should give ~b~Iname[1]~N to ~b~Ifopen()~N, NOT ~b~I*name[1]~N
  213. .R6C1
  214. 6  ~b~I    fp=fopen(~F*~N~b~Iname[1],"r");                          ~N
  215. .WR21C1
  216.     Line 8 needs a ~b~I%s~Ntring format, NOT a ~b~I%f~Nloat !                 
  217. .R8C1
  218. 8  ~b~I        printf("\nSorry, can't open %~Ff~N~b~I",name[1]);    ~N
  219. .WR21C1
  220.     ....and we need to ~b~I#include <stdio.h>~N                                      
  221. .K10,60
  222. as Line 0
  223. .WNK10,32
  224. funtastic!
  225. .WN
  226. 0  ~b~i#include <stdio.h>                                   ~N
  227. 1  ~b~Imain(number,name)                                    ~N
  228. 2  ~b~Iint number;                                          ~N
  229. 3  ~b~Ichar *name[];                                        ~N
  230. 4  ~b~I{                                                    ~N
  231. 5  ~b~I    FILE *fp, *fopen();                              ~N
  232. 6  ~b~I    fp=fopen(name[1],"r");                           ~N
  233. 7  ~b~I    if (fp == NULL) {                                ~N
  234. 8  ~b~I        printf("\nSorry, can't open %s",name[1]);    ~N
  235. 9  ~b~I        exit(0);                                     ~N
  236. 10 ~b~I    }                                                ~N
  237.  
  238.     Let's begin with this introduction ( ...same as before, but with ~Cbugs~N
  239.     removed!) and continue with a program which will read a file on disk
  240.     and count the number of times the letters 'a' through 'z' occur.
  241.  
  242.     We'll compile/link the program under the name ~Icount~N and we will
  243.     type ~Icount sam~N to count the letters 'a'-'z' in a file called ~Isam~N.
  244. .K19,32
  245. how nice!
  246. .WN
  247.  
  248.  
  249.  
  250.  
  251. .T
  252.     counting from 'a to 'z'  
  253. .WN
  254. ~Vchar c;                                         /* characters from file */~N
  255. ~Vint n[26], i;                                   /* count for each letter*/~N
  256. ~b~Ifor (i=0;i<26;i++) n[i]=0;                      /* counts set to zero   */~N
  257. ~b~Ifor (i=0;i<1000;i++)  {                         /* go thru 1000 chars   */~N
  258. ~b~I    c=getc(fp);                                 /* get a char from file */~N
  259. ~b~I    if (c>='a'&& c<='z')  {                     /* is it between a & z? */~N
  260. ~b~I         n[c-'a']++;                            /* yes? increment count */~N 
  261. ~b~I    }                                           /* end of if            */~N
  262. ~b~I}                                               /* end of for           */~N
  263. ~b~Iprintf("\nIn the file %s : ",name[1]);          /* print file name      */~N
  264. ~b~Ifor (i=0;i<=24;i+=2)                            /* go thru alphabet     */~N
  265. ~b~I     printf("\n%c%s%3d%s : %c%s%3d%s",          /* a format string      */~N
  266. ~b~I            'a'+i,  " occurs ",n[i],  " times", /* print letter and     */~N
  267. ~b~I            'a'+i+1," occurs ",n[i+1]," times");/* count for each letter*/~N
  268. ~b~I}                                               /* end of main()        */~N
  269. .R17C1
  270.     Here we declare some stuff, notably the ARRAY ~b~In[26]~N which will hold
  271.     the number of times each of the 26 letters from 'a' to 'z' occur ...hence
  272.     it's an ~b~Iint~Neger ARRAY.
  273. .WR1C1
  274. ~b~Ichar c;                                         /* characters from file */~N
  275. ~b~Iint n[26], i;                                   /* count for each letter*/~N
  276. ~Vfor (i=0;i<26;i++) n[i]=0;                      /* counts set to zero   */~N
  277. .R17C1
  278.                                                                               
  279.                                                                               
  280.                                                                               
  281. .R17C1
  282.     Here we set all the integers in the ARRAY to 0  ..you can never tell what
  283.     garbage might be in those memory locations!
  284. .WR3C1
  285. ~b~Ifor (i=0;i<26;i++) n[i]=0;                      /* counts set to zero   */~N
  286. ~Vfor (i=0;i<1000;i++)  {                         /* go thru 1000 chars   */~N
  287. ~V    c=getc(fp);                                 /* get a char from file */~N
  288. ~V    if (c>='a'&& c<='z')  {                     /* is it between a & z? */~N
  289. .R17C1
  290.                                                                               
  291.                                                                               
  292. .R17C1
  293.     Now we go through 1000 characters in the file and ~b~Igetc(fp)~N each one,
  294.     giving the file ~r~Ipointer~N ~b~Ifp~N to the library function ~b~Igetc()~N
  295.     and getting in ~Ireturn~N a ~b~Ichar~Nacter ~b~Ic~N which we check to see
  296.     if it's GREATER or EQUAL to the character ~b~I'a'~N  AND  ( ~b~I&&~N )
  297.     if it's LESS or EQUAL to the character ~b~I'z'~N.
  298. .WR4C1
  299. ~b~Ifor (i=0;i<1000;i++)  {                         /* go thru 1000 chars   */~N
  300. ~b~I    c=getc(fp);                                 /* get a char from file */~N
  301. ~b~I    if (c>='a'&& c<='z')  {                     /* is it between a & z? */~N
  302. ~V         n[c-'a']++;                            /* yes? increment count */~N 
  303. .R17C1
  304.                                                                               
  305.                                                                               
  306.                                                                               
  307.                                                                               
  308.                                                                               
  309. .R17C1
  310.     ~Iif~N we get a character between 'a' and 'z' we increment the appropriate
  311.     member of our ARRAY ~b~In[]~N ....but how ??
  312. .WR17C1
  313.                                                                               
  314.                                                                               
  315. .R17C1
  316.     Now ~b~Ic~N is a (single) byte in memory, containing the 'value' of the
  317.     ~b~Ic~Nharacter. This 'value' would be ~I65~N for an 'a' and ~I66~N
  318.     for a 'b', etc. (in ASCII). If the 'value' of the ~b~Ic~Nharacter returned
  319.     by ~b~Igetc()~N were ~I69~N (for example) then we must have an 'e' and we
  320.     would increment ~b~In[4]~N (which holds the number of times an 'e' occurs).
  321.     BUT, the 'value' of ~b~Ic~N minus the 'value' of 'a' is ~I69-65=4~N ...
  322.     ...that is, ~b~Ic-'a'~N has the 'value' ~I4~N ...
  323.     SO we increment ~b~In[c-'a']~N ( which WILL increment n[4] ).
  324. .WR7C1
  325. ~b~I         n[c-'a']++;                            /* yes? increment count */~N 
  326. ~V    }                                           /* end of if            */~N
  327. ~V}                                               /* end of for           */~N
  328. .R17C1
  329.                                                                               
  330.                                                                               
  331.                                                                               
  332.                                                                               
  333.                                                                               
  334.                                                                               
  335.                                                                               
  336.                                                                               
  337. .R17C1
  338.     Now we end the ~Iif~N and the ~Ifor~N.
  339.     The numbers in the ARRAY ~b~In[]~N will give us what we want.
  340. .WR8C1
  341. ~b~I    }                                           /* end of if            */~N
  342. ~b~I}                                               /* end of for           */~N
  343. ~Vprintf("\nIn the file %s : ",name[1]);          /* print file name      */~N
  344. .R17C1
  345.                                                                               
  346.                                                                               
  347. .R17C1
  348.     Now (just for kicks) we print the ~b~Iname[1]~N of the file we opened...
  349. .WR10C1
  350. ~b~Iprintf("\nIn the file %s : ",name[1]);          /* print file name      */~N
  351. ~Vfor (i=0;i<=24;i+=2)                            /* go thru alphabet     */~N
  352. .R17C1
  353.                                                                               
  354. .R17C1
  355.     Now we go through all 26 letters ( and all 26 'counts' stored in the
  356.     ARRAY ~b~In[]~N ) but two-at-a-time ( which is why we used ~b~Ii+=2~N
  357.     which adds ~I2~N to ~b~Ii~N each time through the ~Ifor~N loop.
  358. .WR11C1
  359. ~b~Ifor (i=0;i<=24;i+=2)                            /* go thru alphabet     */~N
  360. ~V     printf("\n%c%s%3d%s : %c%s%3d%s",          /* a format string      */~N
  361. ~V            'a'+i,  " occurs ",n[i],  " times", /* print letter and     */~N
  362. ~V            'a'+i+1," occurs ",n[i+1]," times");/* count for each letter*/~N
  363. .R17C1
  364.                                                                               
  365.                                                                               
  366.                                                                               
  367. .R17C1
  368.     Now we print each letter as a ~n~I%c~Nharacter, giving to ~b~Iprintf()~N
  369.     the numbers 'a'+0, then 'a'+1, then 'a'+2, etc. (meaning, the ASCII
  370.     'values' ~I65~N then ~I66~N then ~I67~N etc.).
  371.     We also print ~b~In[0]~N, ~b~In[1]~N, ~b~In[2]~N etc. which are the
  372.     various 'counts' (for an 'a', 'b', 'c', etc.)
  373. .WR12C1
  374. ~V     printf("\n~N~b~I%c%s%3d%s~N~V:%c%s%3d%s",            /* a format string      */~N
  375. .R17C1
  376.                                                                               
  377.                                                                               
  378.                                                                               
  379.                                                                               
  380.                                                                               
  381. .R17C1
  382.     Note that we choose (for variety) to specify a format which says to print:
  383.     First a ~b~I%c~Nharacter then a ~b~I%s~Ntring~N then a ~b~I%d~Necimal (field width ~I3~N)
  384.     then another ~b~I%s~Ntring~N.
  385. .WR12C1
  386. ~V     printf("\n~F%c%s%3d%s~N~V:~F%c%s%3d%s~N~V",            /* a format string      */~N
  387. .R17C1
  388.                                                                               
  389.                                                                               
  390.                                                                               
  391. .R17C1
  392.     ...and we do this TWICE (before we go to a ~b~I\n~Newline) which is why
  393.     we increased ~b~Ii~N by ~I2~N each time through the loop (as in ~b~Ii+=2~N).
  394. .WR12C1
  395. ~b~I     printf("\n%c%s%3d%s : %c%s%3d%s",          /* a format string      */~N
  396. ~V            'a'+i,  " occurs ",n[i],  " times", /* print letter and     */~N
  397. ~b~I            'a'+i+1," occurs ",n[i+1]," times");/* count for each letter*/~N
  398. .R17C1
  399.                                                                               
  400.                                                                               
  401. .R17C1
  402.     This is one of the TWO printouts on each line of the screen:
  403.     First the ~b~I%c~Nharacter (as ~b~I'a'+i~N) then the ~b~I%s~Ntring (" occurs ")
  404.     then the ~b~I%d~Necimal ( ~b~In[i]~N ) with field width ~I3~N, then the ~b~I%s~Ntring
  405.     " times".
  406. .WR13C1
  407. ~b~I            'a'+i,  " occurs ",n[i],  " times", /* print letter and     */~N
  408. ~b~I            'a'+i+1," occurs ",n[i+1]," times");/* count for each letter*/~N
  409. ~V}                                               /* end of main()        */~N
  410. .R17C1
  411.                                                                               
  412.                                                                               
  413.                                                                               
  414.                                                                               
  415. .R17C1
  416.     ..and this (would you believe) is the end of ~b~Imain()~N !
  417.  
  418.     (We really ~Ishould~N provide that 4-space indent!)
  419. .WK2,32
  420. printout??
  421. .WN
  422.     For the program we just wrote (called ~Icount.c~N, before it was compiled
  423.     and linked) we get:
  424.  
  425. ~IA>count count.c~N
  426.  
  427. ~r~IIn the file count.c : ~N
  428. ~r~Ia occurs  18 times : b occurs   3 times~N
  429. ~r~Ic occurs  19 times : d occurs   4 times~N
  430. ~r~Ie occurs  32 times : f occurs  22 times~N
  431. ~r~Ig occurs   3 times : h occurs   9 times~N
  432. ~r~Ii occurs  25 times : j occurs   0 times~N
  433. ~r~Ik occurs   0 times : l occurs   5 times~N
  434. ~r~Im occurs  11 times : n occurs  31 times~N
  435. ~r~Io occurs  19 times : p occurs   9 times~N
  436. ~r~Iq occurs   0 times : r occurs  23 times~N
  437. ~r~Is occurs   9 times : t occurs  22 times~N
  438. ~r~Iu occurs   7 times : v occurs   0 times~N
  439. ~r~Iw occurs   1 times : x occurs   1 times~N
  440. ~r~Iy occurs   2 times : z occurs   3 times~N
  441. .K10,60
  442.  pretty!
  443. .WN
  444. ~b~Ifor (i=0;i<=24;i+=2)                            /* go thru alphabet     */~N
  445. ~b~I     printf("\n%c%s%3d%s : %c%s%3d%s",          /* a format string      */~N
  446. ~b~I            'a'+i,  " occurs ",n[i],  " times", /* print letter and     */~N
  447. ~b~I            'a'+i+1," occurs ",n[i+1]," times");/* count for each letter*/~N
  448.  
  449.     The mechanism for printing two-to-a-line is awkward (!)
  450.     We really want to let ~b~Ii~N go from ~b~I0~N to ~b~I25~N and, each time ~b~Ii~N
  451.     is exactly divisible by ~I2~N, printf a ~b~I\n~Newline.
  452.  
  453.     This 'exact divisibility' can be tested by dividing ~b~I~N by ~I2~N and checking
  454.     if the remainder is zero.
  455.  
  456.     To get the remainder, when ~b~Ii~N is divided by ~I2~N, we use: ~b~Ii%2~N
  457.     (which gives this remainder!).
  458.  
  459. .W
  460. ~b~Ifor (i=0;~Vi<26;i++~N~b~I)                              /* go thru alphabet     */~N
  461. ~V     if (i%~F2~N~V==0)   printf("\n");                /* newline if i%2==0    */~N
  462. ~b~I     printf("%c%s%3d%s",                        /* a format string      */~N
  463. ~b~I            'a'+i, " occurs ",n[i], " times");  /* print letter count   */~N
  464. .R22C1
  465.     ...much nicer code, since we can easily print 3 or 4 to a line by changing
  466.     the number ~V~F2~N.
  467. .WN
  468.  
  469.  
  470. .T
  471.    That's all folks!   
  472. .K16,32
  473. au revoir!
  474.  
  475.  
  476. .q
  477.  
  478.